﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.UI;

namespace Carbon.Web.Forms.Extensions
{
    public delegate void ValidatorFilter(object sender, ValidatorFilterEventArgs args);

    public static class ControlExtensions
    {
        public static TControl GetParentControl<TControl>(this Control control) where TControl : class
        {
            TControl parentControl = GetParentControlOrNull<TControl>(control);

            if (parentControl == null)
                throw new InvalidOperationException("Parent not found.");

            return parentControl;
        }

        public static TControl GetParentControlOrNull<TControl>(this Control control) where TControl : class
        {
            Control parentControl = control.Parent;

            while (!(parentControl is TControl) && parentControl != null)
                parentControl = parentControl.Parent;

            return (parentControl as TControl);
        }

        public static TControl GetParentControlOrNull<TControl, TUnskippableParent>(this Control control) where TControl : class
        {
            Control parentControl = control.Parent;

            while (!(parentControl is TControl) && parentControl != null && !(parentControl is TUnskippableParent))
                parentControl = parentControl.Parent;

            return (parentControl as TControl);
        }

        private static void True(object sender, ValidatorFilterEventArgs args)
        {
            args.DoValidation = true;
        }

        public static bool ValidateRecursively(this Control c)
        {
            return ValidateRecursively(c, null);
        }

        public static bool ValidateRecursively(this Control c, ValidatorFilter filter)
        {
            if (c == null) throw new NullReferenceException("c");

            if (filter == null)
                filter = True;

            bool isValid = true;

            ValidateRecursively(c, c, filter, ref isValid);

            return isValid;
        }

        private static void ValidateRecursively(Control root, Control c, ValidatorFilter filter, ref bool isValid)
        {
            if (!c.Visible)
                return;

            if (c is IValidator)
            {
                IValidator validator = (IValidator)c;

                ValidatorFilterEventArgs args = new ValidatorFilterEventArgs();
                args.Validator = validator;

                filter(root, args);

                if (args.DoValidation)
                {
                    validator.Validate();

                    if (!validator.IsValid)
                        isValid = false;
                }
            }

            foreach (Control c2 in c.Controls)
            {
                ValidateRecursively(root, c2, filter, ref isValid);
            }
        }

        public static Object GetViewModelContext(this Control This)
        {
            IDataProxy proxy = GetParentControl<IDataProxy>(This);
            Object viewModel = proxy.DataContext;
            if (viewModel == null) throw new NullReferenceException("ViewModel");
            return viewModel;
        }
    }
}
